﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace KeyboardCount
{
    public class SendAndRecrive
    {        
        public enum State
        {
            REGISTER        = 1,			//注册请求
            LOGIN			= 2,			//登录请求            
            UPLOAD			= 3,			//上传请求
            DOWNLOAD		= 4,			//下载请求
            LOGOUT			= 5,			//下线请求
            REGISTER_ACK	= 0x1001,			//注册请求ACK
            LOGIN_ACK		= 0x1002,			//登录请求ACK
            UPLOAD_ACK		= 0x1003,			//上传请求ACK
            DOWNLOAD_ACK	= 0x1004,			//下载请求ACK
            LOGOUT_ACK		= 0x1005			//下线请求ACK
        }

        public int SRV_PORT = 6112;
        public string IP = "";

	    public uint cmd;
	    public uint length;
        public uint errno;	
        
        public State state
        {
            set
            {
                cmd = (uint)value;
            }
        }


        public SendAndRecrive()
        {
            IPHostEntry iphost = Dns.GetHostByName("x2.whoops.in");
            foreach (IPAddress ip in iphost.AddressList)
            {
                IP = ip.ToString();
                break;
            }                 
        }

        public void SendMsgHead(TcpClient tcpClient)
        {
            byte[] cmd_s = System.BitConverter.GetBytes(cmd);
            byte[] length_s = System.BitConverter.GetBytes(length);
            byte[] errno_s = System.BitConverter.GetBytes(errno);

            NetworkStream ns = tcpClient.GetStream();

            ns.Write(cmd_s, 0, cmd_s.Length);
            ns.Write(length_s, 0, length_s.Length);
            ns.Write(errno_s, 0, errno_s.Length);

            //ns.Close();
        }

        public void SendUsernameAndPasswd(TcpClient tcpClient, string username, string passwd, State st)
        {
            state = st;
            length = (uint)(username.Length + passwd.Length + 1);
            SendMsgHead(tcpClient);

            byte[] sendMsg = Encoding.UTF8.GetBytes(username + "\n" + passwd);
            NetworkStream ns = tcpClient.GetStream();
            ns.Write(sendMsg, 0, sendMsg.Length);
            //ns.Close();

            ReceiveMsgHead(tcpClient);

            if (st == State.LOGIN)//如果是登录，登录成功后会下载record，并比较最新
            {
                if (errno == 0 && length > 0)
                {
                    string path = Application.StartupPath + "\\temp\\record.dat";
                    FileStream fs = File.Open(path, FileMode.OpenOrCreate);
                    byte[] RcvMsg = new byte[length];
                    ns.Read(RcvMsg, 0, (int)length);

                    fs.Write(RcvMsg, 0, (int)length);
                    fs.Close();
                }
                else if (errno == 0 && length == 0)
                {
                    SendFile(tcpClient, State.UPLOAD);
                }
            }
        }

        public bool SendFile(TcpClient tcpClient, State st)//st为UPLOAD或LOGOUT，退出登录时，也要进行同步一次
        {
            string path = Application.StartupPath + "\\record.dat";
            FileStream fs = File.Open(path, FileMode.Open);
            length = (uint)fs.Length;
            state = st;
            try
            {
                SendMsgHead(tcpClient);

                NetworkStream ns = tcpClient.GetStream();
                byte[] SendMsg = new byte[length];
                fs.Read(SendMsg, 0, (int)length);
                ns.Write(SendMsg, 0, SendMsg.Length);           
                fs.Close();
                //ns.Close();

                ReceiveMsgHead(tcpClient);
                return true;
            }
            catch (System.Exception e)
            {
                fs.Close();//当服务器挂了，必须要把当前打开的文件关掉
                return false;
            }           
        }

        public void ReceiveMsgHead(TcpClient tcpClient)
        {
            NetworkStream ns = tcpClient.GetStream();

            byte[] Rcv1 = new byte[4];
            byte[] Rcv2 = new byte[4];
            byte[] Rcv3 = new byte[4];

            ns.Read(Rcv1, 0, Rcv1.Length);
            ns.Read(Rcv2, 0, Rcv2.Length);
            ns.Read(Rcv3, 0, Rcv3.Length);

            //ns.Close();
            
            cmd = System.BitConverter.ToUInt32(Rcv1, 0);
            length = System.BitConverter.ToUInt32(Rcv2, 0);
            errno = System.BitConverter.ToUInt32(Rcv3, 0);
        }

        public void ReceiveFile(TcpClient tcpClient)
        {
            state = State.DOWNLOAD;
            length = 0;
            SendMsgHead(tcpClient);

            ReceiveMsgHead(tcpClient);

            if (errno == 0)
            {
                string path = Application.StartupPath + "\\record.dat";
                NetworkStream ns = tcpClient.GetStream();
                FileStream fs = File.Open(path, FileMode.OpenOrCreate);
                byte[] RcvMsg = new byte[length];
                ns.Read(RcvMsg, 0, (int)length);

                fs.Write(RcvMsg, 0, (int)length);
                fs.Close();
                //ns.Close();
            }
        }
    }
}
